home *** CD-ROM | disk | FTP | other *** search
- {
- > - trying to produce a 400hz sound in one channel and a 404hz sound in
- > another... How difficult will that be for me? Do I even need to invest
- > in a book, or might someone have some code floating around ... *GRiN*
-
- Well, I can help you for the PC Speaker, I've once picked this source up from a
- Dutch pascal echo:------------------------------
- }
-
- Unit SoundU;
- Interface
- Uses
- Dos;
-
- Procedure DoubleSound(Freq1,Freq2,Duration,SampleFrequency:Real);
- {Play two tones simulatisly: Does sort of:
- Sound(Freq1) + Sound(Freq2)
- Delay(Duration/SampeFrequency*1000)
- NoSound;
- }
-
- Procedure Cli;
- { disable interrupt }
- Inline($fa);
-
- Procedure Sti;
- { enable interrupt }
- Inline($fb);
-
- Implementation
-
- Type { general multitype record for typecasting }
- mtype = Record
- Case Byte Of
- 2: (o,s: Word);
- 4: (l: LongInt);
- End;
-
- Const
- Clk8253 = 1193180; { Clock input to 8253A-5 timerchip }
-
- Var
- old_vector: Pointer; { pointer to original interrupt interrupt }
- dacptr1,dacptr2: Word;{ pointer to start of buffer }
- step1,step2: mtype; { table step value }
- Frac1,Frac2: Word; { fractional part of pointer }
- OnsShotTable: Array[0..255] Of Byte; { Table of Timer 2 ReLoad Values }
- SineTable: Array[0..255] Of Byte; { Sine Table }
- Timer0Reload: Word;
- CountDown: Word;
- factor: Real;
-
- {$S-}
- procedure Int8; Assembler;
- asm
- push ax
- push bx
- push cx
- push ds
- mov ax,Seg @Data
- mov ds,ax
- cmp CountDown,0 { Timeout ? }
- jz @Exit
- dec CountDown
- mov bx,dacptr1 { Get first sample }
- mov ax,step1.o
- add Frac1,ax
- adc bx,step1.s
- mov dacptr1,bx
- and bx,$ff
- mov al,[bx+offset SineTable]
- cbw
- mov cx,ax
- mov bx,dacptr2 { Get second sample }
- mov ax,step2.o
- add Frac2,ax
- adc bx,step2.s
- mov dacptr2,bx
- and bx,$ff
- mov al,[BX+Offset SineTable]
- cbw
- add ax,cx { Add samples }
- sar ax,1 { Adjust }
- add al,$80 { Signed to Absolute }
- mov bx,Offset OnsShotTable { Now, lookup Timer 2 Reload value }
- xlat
- out $42,al { Reload timer channel 2 }
- @Exit:
- mov al,$20 { send End_Of_Interrupt }
- out $20,al
- pop ds
- pop cx
- pop bx
- pop ax
- sti { Position not critical }
- iret
- end;
- {$S+}
-
- Procedure DoubleSound(Freq1,Freq2,Duration,SampleFrequency:Real);
- Var
- I:Byte;
- Begin
- {INIT}
- Timer0Reload:=Round(Clk8253/SampleFrequency);
- SampleFrequency:=Round(Clk8253/Timer0Reload);
- factor:=Clk8253/(SampleFrequency*(256+5));
- For I:=0 To 255 Do OnsShotTable[I]:=1+Round(I*factor);
- For I:=0 To 255 Do SineTable[I]:=Byte(Round(Sin((2*Pi*I)/256)*127));
- { Calculate first SineTable Stepvalue }
- step1.l:=Round(65536.0*freq1*256.0/SampleFrequency);
- dacptr1:=0;
- Frac1:=0;
- { Calculate second SineTable Stepvalue }
- step2.l:=Round(65536.0*freq2*256.0/SampleFrequency);
- dacptr2:=0;
- Frac2:=0;
- { Calculate Timeout value }
- CountDown:=Round(SampleFrequency*duration);
- { OK, time to enable our int8 procedure }
- GetIntVec(8,old_vector);
- cli;
- SetIntVec(8,@Int8);
- { initialize 8253 timer-chip }
- { 8255 PPI, Enable Speaker, Speaker input Gate = output from 8253 channel 2 }
- port[$61]:=port[$61] Or $03;
- port[$43]:=$90; { Channel 2, Read/Write only LSB, Mode 0=OneShot, Binary }
- { Set Interrupt 8 frequency (samplefrequency) }
- port[$43]:=$36; { Channel 0, Read/Write LSB then MSB, Mode 3=SqrW, Binary }
- port[$40]:=Lo(Timer0Reload); { LSB }
- port[$40]:=Hi(Timer0Reload); { MSB }
- sti; { Start PC Speak'ing }
- Repeat
- { BEEP'ING }
- Until CountDown=0;
- cli;
- SetIntVec(8,old_vector); { restore original int8 vector }
- port[$43]:=$36;
- port[$40]:=$00;
- port[$40]:=$00;
- sti;
- end; { output_sound }
-
- end.